package fileMerge;

import fileSplit.FileUtil;

import java.io.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author lxy
 * @Date 2021/12/28 16:33
 * @Description
 */
public class FileMerge {

    public static void main(String[] args) throws IOException {
//        int blockFileSize = 1024 * 1024 * 15;
        memergePartFiles("F:\\work\\program\\LargeFileUpload", ".part",500,  "new.myfile");
    }


    /**
     * @author lxy
     * @date 2021-12-28 16:50
     * @param dirPath 文件存放路径
     * @param partFileSuffix 分片的后缀
     * @param partFileSize 分片文件的大小
     * @param mergeFileName 合并文件的名字
     * @return void
     * @throws
     * @since
     */
    public static void memergePartFiles(String dirPath, String partFileSuffix,int partFileSize, String mergeFileName) throws IOException {
        List<File> partFiles = FileUtil.getDirFiles(dirPath,partFileSuffix);
        Collections.sort(partFiles, new FileComparator());

        RandomAccessFile ra = new RandomAccessFile(mergeFileName, "rw");
        ra.setLength(partFileSize * (partFiles.size() - 1)+ partFiles.get(partFiles.size() - 1).length());
        ra.close();

        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(partFiles.size(),
                partFiles.size() * 3, 1, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(partFiles.size() * 2));
        for (int i = 0; i < partFiles.size(); i++) {
            threadPool.execute(new MergeRunnable(i * partFileSize,mergeFileName, partFiles.get(i)));
        }

    }
    private static class FileComparator implements Comparator<File> {
        public int compare(File o1, File o2) {
            return o1.getName().compareToIgnoreCase(o2.getName());
        }
    }
    private static class MergeRunnable implements Runnable {
        long startPos;
        String mergeFileName;
        File partFile;

        public MergeRunnable(long startPos, String mergeFileName, File partFile) {
            this.startPos = startPos;
            this.mergeFileName = mergeFileName;
            this.partFile = partFile;
        }
        public void run() {
            RandomAccessFile rFile;
            try {
                rFile = new RandomAccessFile(mergeFileName, "rw");
                rFile.seek(startPos);
                FileInputStream fs = new FileInputStream(partFile);
                byte[] b = new byte[fs.available()];
                fs.read(b);
                fs.close();
                rFile.write(b);
                rFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
